package teshop.utils;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.StringTokenizer;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

/**
 * File uploading utility
 * 
 * @author Hryhory Lira (Java Developer)
 *
 */
public class FileUploadingUtil {

	private String path;

	private String filename;

	private FileImageOutputStream output = null;
	
	private ImageWriter writer = null;
	
	private String extension = "jpg";
	
	/**
	 * Default path to the directory of images on server
	 */
	public static final String IMAGE_DIR_PATH = "webapps/TEShop/img/uploaded/";
	
	/**
	 * Default width of resized image
	 */
	public static final int DEFAULT_WIDTH = 500;
	
	/**
	 * Default height of resized image
	 */
	public static final int DEFAULT_HEIGHT = 600;

	/**
	 * Constructor defining image filename and path
	 * @param path path to the server's directory with images
	 * @param filename name of the image file
	 */
	public FileUploadingUtil(String path, String filename) {
		this.path = path;
		this.filename = filename;
	}

	/**
	 * Uploads image obtained from InputStream to the server
	 * @param in input stream with image
	 * @throws IOException
	 */
	public void uploadImage(InputStream in) throws IOException {
		BufferedImage original = ImageIO.read(in);
		uploading(original, "ib");
		BufferedImage resized = resizeImage(original, DEFAULT_WIDTH, DEFAULT_HEIGHT);
		uploading(resized, "is");
	}
	
	/**
	 * Uploads a buffered image to the server
	 * @param input buffered image
	 * @throws IOException
	 */
	private void uploading(BufferedImage input, String prefix)
			throws IOException {
		Iterator<ImageWriter> iter = ImageIO
				.getImageWritersByFormatName(extension);
		if (iter.hasNext()) {
			writer = (ImageWriter) iter.next();
			ImageWriteParam iwp = writer.getDefaultWriteParam();
			iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
			float values[] = iwp.getCompressionQualityValues();
			// Write one for each compression values
			for (int i = 0, n = values.length; i < n; i++) {
				iwp.setCompressionQuality(values[i]);
				writeToDirectory(input, iwp, prefix);
			}
			output.close();
			input.flush();
		}
	}

	/**
	 * Writes a buffered image with write parameter to the directory
	 * @param input BufferedImage
	 * @param iwp image write parameter
	 * @throws IOException
	 */
	private void writeToDirectory(BufferedImage input, ImageWriteParam iwp, String prefix)
	throws IOException {
		String newName = path + prefix + filename + "." + extension;
		File outFile = new File(newName);
		output = new FileImageOutputStream(outFile);
		writer.setOutput(output);
		IIOImage image = new IIOImage(input, null, null);
		writer.write(null, image, iwp);
	}
	
	/**
	 * Resizes an image to (w, h)
	 * @param original original image
	 * @return resized buffered image
	 * @throws IOException
	 */
	private BufferedImage resizeImage(BufferedImage original, int w, int h)
	throws IOException {
		int width = original.getWidth();
		int height = original.getHeight();
		
		if (width >= height)
			h = w * height / width;
		else
			w = h * width / height;
		
		Image resizedImage = original.getScaledInstance(w, h, Image.SCALE_SMOOTH);
		BufferedImage resizedBI = new BufferedImage(w, h,
				BufferedImage.TYPE_INT_RGB);

		Graphics graphBI = resizedBI.getGraphics();
		graphBI.drawImage(resizedImage, 0, 0, null);
		
		return resizedBI;
	}
	
	/**
	 * Parses an extension of the file (e.g. "gif", "jpg").
	 * Returns full path to image
	 * @param filename file name
	 */
	public void parseExtension(String filename) {
		StringTokenizer st = new StringTokenizer(filename, ".");
		while (st.hasMoreTokens()) {
			extension = st.nextToken();
		}
	}

}
